__metaclass__ = type

import sys, os
import time

#try to get work dir
workdir = sys.argv[0][ 0:sys.argv[0].rfind('/') ]
appname = sys.argv[0][ (sys.argv[0].rfind('/')+1) : len(sys.argv[0]) ]
cmd = sys.argv[1]

def createDeamon(cmd):
    print 'start fork process:'+cmd
    # create - fork 1
    try:
        pid = os.fork()
        if pid > 0: 
            return 0
    except OSError, error:
        print 'fork #1 failed: %d (%s)' % (error.errno, error.strerror)
        #exit(1)
        return 1
    
    # it separates the son from the father
    os.chdir('/')
    os.setsid()
    os.umask(0)

    # create - fork 2
    try:
        pid = os.fork()
        if pid > 0:
            os._exit(0)
        
    except OSError, error:
        print 'fork #2 failed: %d (%s)' % (error.errno, error.strerror)
        os._exit(1)

    os.system(cmd)
    os._exit(0)

def delfile(path):
    try:
        f = open(path)
        f.close()
        os.system("rm " + path)
    
    except IOError:
        pass

class CServer:
    Inited = 0
    Starting = 1
    Running = 2
    Killing = 3
    Terminated = 4
    
    def __init__(self):
        self.mStatus = CServer.Inited  
    
    def start(self):
        '''start a server
        
        Inited-->
        Terminated-->
        
        @return: 0 means starting, -1 means not start.        
        '''
        self.mStatus = CServer.Starting
        return 0
    
    def kill(self):
        '''kill a server
    
        Running-->
        
        @return: 0 means terminated, -1 means not kill, server is running.       
        '''
        self.mStatus = CServer.Killing
        return 0
        
    def status(self):
        '''return the state of server
        
        '''
        return self.mStatus
    
class CBroadcastServer(CServer):
    def __init__(self):
        CServer.__init__(self)
    
    def status(self):
        bTerminated = 0
        fpid = None
        fcmdline = None
        
        try:
            fpid = open(workdir + '/testbroadcastserver.py.pid')
            pid = fpid.read()
            
            fcmdline = open('/proc'+'/'+pid+'/cmdline')
            cmdline = fcmdline.read()
            
            if 'testbroadcastserver' in cmdline:
                if self.mStatus == CServer.Starting:
                    self.mStatus = CServer.Running
                    
            else:
                bTerminated = 1
            
        except IOError:
            bTerminated = 1
            
        finally:
            if fpid:
                fpid.close()
            
            if fcmdline:
                fcmdline.close()
                
        if bTerminated:
            if self.mStatus == CServer.Killing:
                self.mStatus = CServer.Terminated
            
        return CServer.status(self)
    
    def start(self):
        state = self.status()
        
        if CServer.Running == state or CServer.Starting == state:
            return 1
        
        if CServer.Killing == state or CServer.start(self) < 0:
            return -1
            
        delfile(workdir + '/testbroadcastserver.py.pid')
        createDeamon(workdir + '/python-android-install/bin/python ' +  workdir + "/testbroadcastserver.py")
    
        return 0
    
    def kill(self):
        state = self.status()
        
        if CServer.Killing == state or CServer.Terminated == state:
            return 1
        
        if CServer.Starting == state or CServer.Inited == state or \
                CServer.kill(self) < 0:
            return -1
        
        pid = 0
        fpid = None
        fcmdline = None
        try:
            fpid = open(workdir + '/testbroadcastserver.py.pid')
            pid = fpid.read()
            
            fcmdline = open('/proc'+'/'+pid+'/cmdline')
            cmdline = fcmdline.read()
            
            if 'testbroadcastserver' in cmdline:
                print 'kill testbroadcastserver.py'
                os.system('kill ' + pid)
                
            else:
                pid = 0                
            
        except IOError:
            pid = 0
            
        finally:
            if fpid:
                fpid.close()
            
            if fcmdline:
                fcmdline.close()
                
            if pid:
                pass
            else:
                print 'testbroadcastserver.py is not running'
                
        return 0
        
class CNginxServer(CServer):
    def __init__(self):
        CServer.__init__(self)
    
    def status(self):
        bTerminated = 0
        fpid = None
        fcmdline = None
    
        try:
            fpid = open(workdir + '/nginx-android-install/logs/nginx.pid')
            pid = fpid.read().strip()
            
            fcmdline = open('/proc'+'/'+pid+'/cmdline')
            cmdline = fcmdline.read()
            
            if '/sbin/nginx' in cmdline:
                if self.mStatus == CServer.Starting:
                    self.mStatus = CServer.Running
                    
            else:
                bTerminated = 1
                
        except IOError:
            bTerminated = 1
            
        finally:
            if fpid:
                fpid.close()
            
            if fcmdline:
                fcmdline.close()
                
        if bTerminated:
            if self.mStatus == CServer.Killing:
                self.mStatus = CServer.Terminated
            
        return CServer.status(self)
        
    def start(self):
        state = self.status()
        
        if CServer.Running == state or CServer.Starting == state:
            return 1
        
        if CServer.Killing == state or CServer.start(self) < 0:
            return -1
         
        delfile(workdir + '/nginx-android-install/logs/nginx.pid')
        print 'start nginx:ret:', os.system(workdir + '/nginx-android-install/sbin/nginx' + ' -p ' + workdir+'/nginx-android-install')
    
        return 0
    
    def kill(self):
        state = self.status()
        
        if CServer.Killing == state or CServer.Terminated == state:
            return 1
        
        if CServer.Starting == state or CServer.Inited == state or \
                CServer.kill(self) < 0:
            return -1
        
        pid = 0
        fpid = None
        fcmdline = None
        try:
            fpid = open(workdir + '/nginx-android-install/logs/nginx.pid')
            pid = fpid.read().strip()
            
            fcmdline = open('/proc'+'/'+pid+'/cmdline')
            cmdline = fcmdline.read()
            
            if '/sbin/nginx' in cmdline:
                print 'kill nginx'
                os.system('kill ' + pid)
                
            else:
                pid = 0
                
        except IOError:
            pid = 0
            
        finally:
            if fpid:
                fpid.close()
            
            if fcmdline:
                fcmdline.close()
        
            if pid:
                pass
            else:
                print 'nginx is not running'
                
        return 0
                
class CWebServer(CServer):
    def __init__(self):
        CServer.__init__(self)
    
    def status(self):
        bTerminated = 0
        fpid = None
        fcmdline = None
    
        try:
            fpid = open(workdir + '/testweb.py.pid')
            pid = fpid.read()
            
            fcmdline = open('/proc'+'/'+pid+'/cmdline')
            cmdline = fcmdline.read()
            
            if 'testweb.py' in cmdline:
                if self.mStatus == CServer.Starting:
                    self.mStatus = CServer.Running
                    
            else:
                bTerminated = 1
                
        except IOError:
            bTerminated = 1
            
        finally:
            if fpid:
                fpid.close()
            
            if fcmdline:
                fcmdline.close()
        
        if bTerminated:
            if self.mStatus == CServer.Killing:
                self.mStatus = CServer.Terminated
            
        return CServer.status(self)
    
    def start(self):
        state = self.status()
        
        if CServer.Running == state or CServer.Starting == state:
            return 1
        
        if CServer.Killing == state or CServer.start(self) < 0:
            return -1
         
        delfile(workdir + '/testweb.py.pid')
        createDeamon(workdir + '/python-android-install/bin/python ' +  workdir + "/testweb.py 8899")
    
        return 0
    
    def kill(self):
        state = self.status()
        
        if CServer.Killing == state or CServer.Terminated == state:
            return 1
        
        if CServer.Starting == state or CServer.Inited == state or \
                CServer.kill(self) < 0:
            return -1
        
        pid = 0
        fpid = None
        fcmdline = None
        try:
            fpid = open(workdir + '/testweb.py.pid')
            pid = fpid.read()
            
            fcmdline = open('/proc'+'/'+pid+'/cmdline')
            cmdline = fcmdline.read()
            
            if 'testweb.py' in cmdline:
                print 'kill testweb.py'
                os.system('kill ' + pid)
                
            else:
                pid = 0
            
        except IOError:
            pid = 0
            
        finally:
            if fpid:
                fpid.close()
            
            if fcmdline:
                fcmdline.close() 
                
            if pid:
                pass
            else:
                print 'testweb.py is not running'
                
        return 0
         
class CMicrohttpdServer(CServer):
    def __init__(self):
        CServer.__init__(self)
    
    def status(self):
        bTerminated = 0
        fpid = None
        fcmdline = None
    
        try:
            fpid = open(workdir + '/testmicrohttpd.pid')
            pid = fpid.read()
            
            fcmdline = open('/proc'+'/'+pid+'/cmdline')
            cmdline = fcmdline.read()
            
            if 'testmicrohttpd' in cmdline:
                if self.mStatus == CServer.Starting:
                    self.mStatus = CServer.Running
                    
            else:
                bTerminated = 1
                
        except IOError:
            bTerminated = 1
            
        finally:
            if fpid:
                fpid.close()
            
            if fcmdline:
                fcmdline.close()
             
        if bTerminated:
            if self.mStatus == CServer.Killing:
                self.mStatus = CServer.Terminated
            
        return CServer.status(self)
         
    def start(self):
        state = self.status()
        
        if CServer.Running == state or CServer.Starting == state:
            return 1
        
        if CServer.Killing == state or CServer.start(self) < 0:
            return -1
         
        delfile(workdir + '/testmicrohttpd.pid')
        createDeamon('LD_LIBRARY_PATH='+workdir+'/lib-android-install '+ workdir + "/testmicrohttpd 8800")   
        
        return 0
    
    def kill(self):
        state = self.status()
        
        if CServer.Killing == state or CServer.Terminated == state:
            return 1
        
        if CServer.Starting == state or CServer.Inited == state or \
                CServer.kill(self) < 0:
            return -1
        
        
        pid = 0
        fpid = None
        fcmdline = None
        try:
            fpid = open(workdir + '/testmicrohttpd.pid')
            pid = fpid.read()
            
            fcmdline = open('/proc'+'/'+pid+'/cmdline')
            cmdline = fcmdline.read()
            
            if 'testmicrohttpd' in cmdline:
                print 'kill testmicrohttpd'
                os.system('kill ' + pid)
                
            else:
                pid = 0
            
        except IOError:
            pid = 0
            
        finally:
            if fpid:
                fpid.close()
            
            if fcmdline:
                fcmdline.close()
            
            if pid:
                pass
            else:
                print 'testmicrohttpd is not running'    
        
        return 0
                            
class CFcgiServer(CServer):
    def __init__(self):
        CServer.__init__(self)
    
    def status(self):
        bTerminated = 0
        fpid = None
        fcmdline = None
    
        try:
            fpid = open(workdir + '/testfcgi.py.pid')
            line = fpid.readline() 
            pid = str( line[line.find('PID:')+4 : len(line)] ).strip()
                    
            fcmdline = open('/proc'+'/'+pid+'/cmdline')
            cmdline = fcmdline.read()
            
            if 'testfcgi.py' in cmdline:
                if self.mStatus == CServer.Starting:
                    self.mStatus = CServer.Running
                    
            else:
                bTerminated = 1
                
        except IOError:
            bTerminated = 1
            
        finally:
            if fpid:
                fpid.close()
            
            if fcmdline:
                fcmdline.close()
        
        if bTerminated:
            if self.mStatus == CServer.Killing:
                self.mStatus = CServer.Terminated
            
        return CServer.status(self) 
    
    def start(self):
        state = self.status()
        
        if CServer.Running == state or CServer.Starting == state:
            return 1
        
        if CServer.Killing == state or CServer.start(self) < 0:
            return -1
         
        delfile(workdir + '/testfcgi.py.pid')
        
        cmd = workdir + '/spawn-fcgi-android-install/bin/spawn-fcgi  -a 127.0.0.1 -p 9003 -F 1  -f " ' \
                      + workdir + '/python-android-install/bin/python ' + workdir + '/testfcgi.py " ' \
                       + ' >> ' + workdir + '/testfcgi.py.pid'
        
        print 'run:',cmd
        os.system(cmd)
        
        return 0

    def kill(self):
        state = self.status()
        
        if CServer.Killing == state or CServer.Terminated == state:
            return 1
        
        if CServer.Starting == state or CServer.Inited == state or \
                CServer.kill(self) < 0:
            return -1
        
        
        pid = 0
        fpid = None
        
        try:
            fpid = open(workdir + '/testfcgi.py.pid')
            while(1):
                line = fpid.readline()
                if '' == line:
                    break
                 
                pid = str( line[line.find('PID:')+4 : len(line)] ).strip()
                
                fcmdline = None
                try:        
                    fcmdline = open('/proc'+'/'+pid+'/cmdline')
                    cmdline = fcmdline.read()
                    
                    if 'testfcgi.py' in cmdline:
                        print 'kill testfcgi', pid
                        os.system('kill ' + pid)
                    else:
                        pid = 0
                
                except IOError:
                    pid = 0
                    
                finally:
                    if fcmdline:
                        fcmdline.close()
            
        except IOError:
            pid = 0
            
        finally:
            if fpid:
                fpid.close()
            
            if pid:
                pass
            else:
                print 'testfcgi.py is not running'
        
        return 0
                
servers = []
servers.append( CBroadcastServer() )
servers.append( CNginxServer() )
servers.append( CWebServer() )
servers.append( CMicrohttpdServer() )
servers.append( CFcgiServer() )
        

    
def startServer():
    for svr in servers:
        #restore state to init
        svr.mStatus = CServer.Inited
        
        tStart = time.time()
        
        svr.start()
        while 1:
            if CServer.Running == svr.status():
                break
            else:
                time.sleep(1)
                
        tEnd = time.time()
        fullname = str(svr.__class__)
        name = str(fullname[ fullname.rfind('C'):len(fullname)-2 ])
        
        print 'start server<'+name+'>cost:'+str(tEnd-tStart)+' sec' 


    
def killServer():
    for svr in servers:
        #restore state to Running
        svr.mStatus = CServer.Running
        
        tStart = time.time()
        
        svr.kill()
        while 1:
            if CServer.Terminated == svr.status():
                break
            else:
                time.sleep(1)
                
        tEnd = time.time()
        
        fullname = str(svr.__class__)
        name = str(fullname[ fullname.rfind('C'):len(fullname)-2 ])
        
        print 'kill server<'+name+'>cost:'+str(tEnd-tStart)+' sec'       

if cmd == 'start':
    print 'sct:start server'
    killServer()
    startServer()
    
elif cmd == 'kill':
    print 'sct:kill server'
    killServer()
    
elif cmd == 'restart':
    print 'sct:restart server'
    killServer()
    startServer()
    
elif cmd == 'reset':
    print 'sct:reset server'
    killServer()
    startServer()
 
print 'servermanager finish ' + cmd + ' job'
exit(0)